package cn.scy.util;

import cn.scy.base.guangzlt.BaseRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 公共签名工具类
 *
 * @author scy
 */
@Slf4j
public final class SignUtils {

    private SignUtils() {
    }

    /**
     * 获取签名
     *
     * @param params 参数
     * @param appKey 应用密钥
     * @return 签名值
     */
    public static String getSign(Map<String, Object> params, String appKey) {
        StringBuilder linkString = createLinkString(params, true);
        linkString.append("&appKey=").append(appKey);
        log.info("signStringBuilder: {}", linkString);
        return DigestUtils.md5Hex(linkString.toString()).toUpperCase();
    }

    public static <T extends BaseRequest> void sign(T request, String appId, String appKey) {
        request.setAppId(appId);
        request.setTimestamp(System.currentTimeMillis());
        request.setSign(null);

        JSONObject params = JSON.parseObject(JSONObject.toJSONString(request));
        StringBuilder linkString = createLinkString(params, true);
        linkString.append("&appKey=").append(appKey);
        log.info("SignUtils sign linkString : {}", linkString);

        request.setSign(DigestUtils.md5Hex(linkString.toString()).toUpperCase());
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *
     * @param params 需要排序并参与字符拼接的参数组
     * @param flag   是否拼接 = 和 &
     * @return 拼接后字符串
     */
    public static StringBuilder createLinkString(Map<String, Object> params, boolean flag) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        StringBuilder sb = new StringBuilder();
        String value;
        Object temp;
        for (String key : keys) {
            temp = params.get(key);
            value = String.valueOf(temp);
            if (temp instanceof Collection) {
                value = JSON.toJSONString(params.get(key));
            }
            if (temp instanceof Map) {
                value = JSON.toJSONString(params.get(key));
            }
            if (StringUtils.hasLength(value.trim())) {
                if (flag) {
                    if (sb.length() > 0) {
                        sb.append("&");
                    }
                    sb.append(key).append("=").append(value.trim());
                } else {
                    sb.append(key).append(value.trim());
                }
            }
        }
        return sb;
    }

}
